package com.springboot.service.impl;

import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import com.alibaba.fastjson.JSON;
import com.springboot.config.security.JwtConfig;
import com.springboot.constant.WxUserExecl;
import com.springboot.dto.WxUserInfoDTO;
import com.springboot.entity.WxUser;
import com.springboot.enums.ErrorEnum;
import com.springboot.enums.WxUserRole;
import com.springboot.enums.WxUserStatus;
import com.springboot.exception.MyException;
import com.springboot.repository.WxUserRepository;
import com.springboot.service.WxUserService;
import com.springboot.utils.CopyObjectUtil;
import com.springboot.utils.ExeclUtil;
import com.springboot.utils.QrCodeUtil;
import com.springboot.utils.UserUtil;
import com.springboot.vo.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.Predicate;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * @author: lzh
 */
@Service
public class WxUserServiceImpl implements WxUserService {

    @Autowired
    JwtConfig jwtConfig;


    @Autowired
    WxUserRepository wxUserRepository;

    @Override
    public WxUserVO getWxUserInfo() {
        WxUser wxUser = UserUtil.getCurrentUser();
        WxUserVO wxUserVO = new WxUserVO();
        BeanUtils.copyProperties(wxUser, wxUserVO);
        return wxUserVO;
    }

    @Override
    public byte[] createQrCode() {
        WxUser wxUser = UserUtil.getCurrentUser();
        WxCheckedUserVO wxCheckedUserVO = new WxCheckedUserVO();
        BeanUtils.copyProperties(wxUser, wxCheckedUserVO);
        //把对象转换成json
        String content = JSON.toJSONString(wxCheckedUserVO);
        ByteArrayOutputStream byteArrayOutputStream = null;
        try {
            //生成二维码
            byteArrayOutputStream = QrCodeUtil.writeToStream(content);
        } catch (Exception e) {
            e.printStackTrace();
            throw new MyException(ErrorEnum.CREATE_QRCODE_ERROR);
        }
        return byteArrayOutputStream.toByteArray();
    }

    @Override
    public void saveWxUserInfo(WxUserInfoDTO wxUserInfoDTO) {
        WxUser wxUser = wxUserRepository.getOne(wxUserInfoDTO.getId());
        CopyObjectUtil.copyNotNull(wxUserInfoDTO, wxUser);
        wxUserRepository.save(wxUser);
    }

    @Override
    public WxUserLoginVO wxLogin(String openid) {
        WxUser wxUser = wxUserRepository.findByOpenid(openid);
        if (wxUser == null) {
            throw new MyException(ErrorEnum.WX_USER_LOGIN_MISS);
        }
        if(wxUser.getIsLock()) {
            throw new MyException(ErrorEnum.WX_USER_LOCKED);
        }
        String token = jwtConfig.getToken(openid, true);
        WxUserLoginVO wxUserLoginVO = new WxUserLoginVO(token, wxUser);
        return wxUserLoginVO;
    }

    @Override
    public WxUserLoginVO wxRegister(WxMaUserInfo userInfo) {
        WxUser userByOpenid = wxUserRepository.findByOpenid(userInfo.getOpenId());
        if(Objects.nonNull(userByOpenid)) {
            throw new MyException(ErrorEnum.WX_USER_EXIST);
        }
        WxUser wxUser = WxUser.builder()
                .openid(userInfo.getOpenId())
                .name(userInfo.getNickName())
                .avatarUrl(userInfo.getAvatarUrl())
                .accessNum(0)
                .isProsecutor(false)
                .isLock(false)
                .status(WxUserStatus.HEALTHY.getMsg())
                .gender("1".equals(userInfo.getGender()) ? "男" : "女")
                .build();
        WxUser retWxUser = wxUserRepository.save(wxUser);
        WxUserLoginVO wxUserLoginVO = new WxUserLoginVO(jwtConfig.getToken(retWxUser.getOpenid(), true), retWxUser);
        return wxUserLoginVO;
    }

    @Override
    public PageVO getWxUserList(Integer pageNum, Integer pageSize, String keywords, WxUserRole wxUserRole) {
        Page<WxUser> wxUserPage = wxUserRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            //关键字查询
            if (!StringUtils.isEmpty(keywords)) {
                List<Predicate> orList = new ArrayList<>();
                orList.add(criteriaBuilder.like(root.get("name"), "%" + keywords + "%"));
                orList.add(criteriaBuilder.like(root.get("idCard"), "%" + keywords + "%"));
                list.add(criteriaBuilder.or(orList.toArray(new Predicate[orList.size()])));
            }
            //用户身份查询
            if (Objects.nonNull(wxUserRole)) {
                if (wxUserRole.compareTo(WxUserRole.PROSECUTOR) == 0) {
                    list.add(criteriaBuilder.equal(root.get("isProsecutor"), true));
                } else if (wxUserRole.compareTo(WxUserRole.REGIDENT) == 0) {
                    list.add(criteriaBuilder.equal(root.get("isRegident"), true));
                } else if (wxUserRole.compareTo(WxUserRole.MIGRANTS) == 0) {
                    list.add(criteriaBuilder.equal(root.get("isRegident"), false));
                }
            }
            criteriaQuery.orderBy(criteriaBuilder.desc(root.get("createTime")));
            return criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
        }, PageRequest.of(pageNum - 1, pageSize));
        //封装数据
        PageVO pageVO = PageVO.convert(wxUserPage);
        List<WxUserListVO> content = wxUserPage.getContent().stream().map(wxUser -> {
            WxUserListVO wxUserListVO = new WxUserListVO();
            BeanUtils.copyProperties(wxUser, wxUserListVO);
            wxUserListVO.setGender(wxUser.getGender());
            return wxUserListVO;
        }).collect(Collectors.toList());
        pageVO.setContent(content);
        return pageVO;
    }

    @Override
    public void setProsecutor(Integer id) {
        WxUser wxUser = wxUserRepository.getOne(id);
        wxUser.setIsProsecutor(!wxUser.getIsProsecutor());
        wxUserRepository.save(wxUser);
    }

    @Override
    public void setLock(Integer id) {
        WxUser wxUser = wxUserRepository.getOne(id);
        wxUser.setIsLock(!wxUser.getIsLock());
        wxUserRepository.save(wxUser);
    }

    @Override
    public HSSFWorkbook dowloadExecl() {
        List<WxUser> wxUserList = wxUserRepository.findAll();
        List<List<String>> values = new ArrayList<>();
        for (WxUser wxUser : wxUserList) {
            List<String> value = new ArrayList<>();
            if(wxUser.getIsRegident()) {
                value.add("住户");
            } else {
                value.add("外来人员");
            }
            value.add(wxUser.getStatus());
            value.add(wxUser.getName());
            value.add(wxUser.getGender());
            value.add(wxUser.getIdCard());
            value.add(wxUser.getRoomNumber());
            value.add(String.valueOf(wxUser.getAccessNum()));
            if(wxUser.getIsProsecutor()) {
                value.add("是");
            } else {
                value.add("否");
            }
            if(wxUser.getIsLock()) {
                value.add("已锁定");
            } else {
                value.add("正常");
            }
            values.add(value);
        }
        HSSFWorkbook wb = ExeclUtil.getHSSFWorkbook(WxUserExecl.SHEETNAME, WxUserExecl.TITLES, values);
        return wb;
    }


}
